# Kestrel: An XMPP-based Many-Task Computing Scheduler
# Author: Lance Stout <lancestout@gmail.com>
#
# Copyright 2009-2010 Clemson University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


class Task(object):
    """
    Data structure representing a task.

    A task is a single instance of a job that has
    a unique identifier among other instances from
    the same job. A job is simply a request for a
    command to be executed.
    """

    def __init__(self, data=None):
        """
        Instantiate a task object given a dictionary
        representation of a task that can include:

        source (int):
          The name of the manager issuing the task.
        job_id (int):
          The ID of the job requesting the task.
        task_id (int):
          A unique number identifying the task among
          others for this job.
        command (list|string):
          If a string, the command is the path to an
          executable file. If it is a list, then each
          item in the list is an executable and will
          be executed in the order given.
        cleanup (string):
          An optional path to an executable responsible
          for cleaning up and resetting any resources used.
          If the agent processing the task goes offline
          while executing the cleanup command, the task
          is still considered completed.
        """
        if data is None:
            data = {}

        # The source, job ID, and task ID provide
        # a globally unique ID for the task.
        self.source = data.get('source', '')
        self.job_id = int(data.get('job_id', 0))
        self.task_id = int(data.get('task_id', 0))

        # Executing the main command is the
        # purpose for the task.
        self.command = data.get('command', '')

        # Once the main command has completed,
        # the cleanup command is executed. If
        # a task is terminated by an agent going
        # offline while in the cleanup stage, the
        # task will be considered completed and
        # will not be rescheduled.
        self.cleanup = data.get('cleanup', '')

        # Only the output from standard out and
        # standard error are tracked. Any other
        # outputs must be managed by the main
        # command itself.
        self.stdout = ''
        self.stderr = ''

    def id(self):
        """
        Return the task's unique ID, which is composed of a
        manager name, job ID, and a task number.
        """
        return (self.source, self.job_id, self.task_id)

    def __repr__(self):
        return "(JobID: %d, TaskID: %d)" % (self.job_id, self.task_id)
